package cn.icanci.loopstack.plugin.dalgen.engine.impl;

import cn.icanci.loopstack.plugin.dalgen.config.GlobalConfig;
import cn.icanci.loopstack.plugin.dalgen.engine.AbstractGeneralEngine;
import cn.icanci.loopstack.plugin.dalgen.model.ClassInfoVO;
import cn.icanci.loopstack.plugin.dalgen.model.ConfigurationInfoVO;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

/**
 * 默认实现类
 *
 * @author icanci
 * @since 1.0 Created in 2022/05/13 18:53
 */
public class DefaultEngine extends AbstractGeneralEngine {
    /**
     * 系统分隔符
     */
    private static final String       SPACER            = File.separator;
    /**
     * java 源码路径
     */
    private static final String       SRC_MAIN_JAVA     = SPACER + "src" + SPACER + "main" + SPACER + "java" + SPACER;
    /**
     * resources 路径
     */
    private static final String       SRC_MAIN_RESOURCE = SPACER + "src" + SPACER + "main" + SPACER + "resources" + SPACER;
    /**
     * config 对象
     */
    private final ConfigurationInfoVO config;
    /**
     * configuration 对象
     */
    private final Configuration       configuration;

    /**
     * 默认执行引擎
     */
    public DefaultEngine(String path) {
        config = GlobalConfig.getGobleConfig(path);
        configuration = AbstractGeneralEngine.getConfiguration();
    }

    /***
     * 生成Class文件
     *
     * @param classInfo      ClassInfo
     * @param templateName   模板地址
     * @param classSuffix    文件后缀
     */
    private void genClass(ClassInfoVO classInfo, String templateName, String parentPackage, String className, String classSuffix) {
        // 构建文件地址
        String path = config.getPackageName().replace(".", SPACER);
        // 磁盘上真实全路径地址
        String filePath = config.getRealProjectCodePath() + SRC_MAIN_JAVA + path + SPACER + parentPackage.replace(".", SPACER) + SPACER + className + classSuffix;
        process(classInfo, templateName, filePath);
    }

    /***
     * FreeMarker 模板固定方法
     *
     * @param classInfo classInfo
     * @param templateName templateName
     * @param filePath filePath
     */
    private void process(ClassInfoVO classInfo, String templateName, String filePath) {
        try {
            System.out.println("process 文件地址: " + filePath);

            File file = new File(filePath);
            file.getParentFile().mkdirs();

            Writer writer = new FileWriter(filePath);

            Template template = configuration.getTemplate(templateName);

            Map<String, Object> params = new HashMap<>(16);
            params.put("classInfo", classInfo);
            params.put("authorName", config.getAuthorName());
            params.put("packageName", config.getPackageName());
            params.put("genConfig", config);
            template.process(params, writer);
            writer.flush();
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成持久层类
     *
     * @param classInfo classInfo
     */
    @Override
    public void genRepositoryClass(ClassInfoVO classInfo) {
        genClass(classInfo, "code-generator/mybatis/mapper.ftl", "mapper", classInfo.getRealClassMapperName(), "Mapper.java");
    }

    /**
     * 生成持久层xml
     *
     * @param classInfo classInfo
     * @param module db模块
     */
    @Override
    public void genRepositoryXml(ClassInfoVO classInfo, String module) {
        // 构建文件地址
        String rootPath = config.getRealProjectCodePath();

        String filePath = rootPath + SRC_MAIN_RESOURCE + "mybatis" + SPACER + "mapper" + SPACER + classInfo.getRealClassMapperName() + "Mapper.xml";
        if (StringUtils.isNotBlank(module)) {
            filePath = rootPath + SRC_MAIN_RESOURCE + "mybatis" + SPACER + module + SPACER + "mapper" + SPACER + classInfo.getRealClassMapperName() + "Mapper.xml";
        }

        process(classInfo, "code-generator/mybatis/mapper_xml.ftl", filePath);
    }

    /**
     * 生成映射Mapping类
     *
     * @param classInfo classInfo
     * @param module db模块
     */
    @Override
    public void genMapstructClass(ClassInfoVO classInfo, String module) {
        genClass(classInfo, "code-generator/mybatis/mapping.ftl", "mapping", classInfo.getRealClassName(), "Mapping.java");
    }

    /**
     * 生成实体
     *
     * @param classInfo classInfo
     */
    @Override
    public void genEntity(ClassInfoVO classInfo) {
        genClass(classInfo, "code-generator/mybatis/model.ftl", "entity", classInfo.getRealClassName(), ".java");
    }

    /**
     * 生成实体VO
     *
     * @param classInfo classInfo
     */
    @Override
    public void genMapstructEntity(ClassInfoVO classInfo) {
        genClass(classInfo, "code-generator/mybatis/modelVO.ftl", "entityvo", classInfo.getRealClassVOName(), ".java");
    }

    public ConfigurationInfoVO getConfig() {
        return config;
    }
}